
package com.hlkj.pay.app.merchant.ext.impl.baofu.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.pay.app.merchant.ext.dto.report.ChannelMerchantReportContext;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.dto.merchant.MerchantAccessScene;
import com.hlkj.pay.dto.merchant.config.MerchantReportConfigDto;
import com.hlkj.pay.dto.merchant.report.MerchantReportDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.*;
import com.hlkj.pay.infrastructure.model.pay.PayChannelDictDO;
import com.hlkj.pay.util.FileUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 汇付 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
@Service
public class BaoFuMerchantParamsHandle extends BaofuMerchantCommonParamsHandle {

    @Value("${hlkj.upload.directory}")
    public String uploadDirectory;

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    public CommonResult<Void> merchantReportParamsCheck(ChannelMerchantReportContext channelMerchantReportContext) {
        MerchantReportDto merchantReportDto = channelMerchantReportContext.getMerchantReportDto();
        MerchantReportInfoDO merchantReportInfo = merchantReportDto.getMerchantReportInfo();
        MerchantReportBusinessDO merchantReportBusiness = merchantReportDto.getMerchantReportBusiness();
        MerchantLicenseDO merchantReportLicense = merchantReportDto.getMerchantReportLicense();
        switch (MerchantEnum.MERCHANT_TYPE.from(merchantReportInfo.getType())) {
            case PERSONAL:
                return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 不支付个人进件");
            default:
                if (StringUtils.isEmpty(merchantReportBusiness.getEconomyType())) {
                    return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 企业经济性质不能为空");
                }
                if (StringUtils.isEmpty(merchantReportBusiness.getCompanySizeType())) {
                    return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 企业规模不能为空");
                }
                if (StringUtils.isEmpty(merchantReportBusiness.getListingType())) {
                    return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 上市类型不能为空");
                }

        }
        MerchantReportConfigDto merchantReportConfigDto = channelMerchantReportContext.getMerchantReportConfigDto();
        if (merchantReportConfigDto == null || CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantReportConfigDto.getStatus())) {
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 报备费率不能为空");
        }
        if (merchantReportConfigDto.getInFeeType() == null || merchantReportConfigDto.getOutFeeType() == null) {
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 报备费率不能为空");
        }
        String companyType = companyType(merchantReportLicense.getCompanyType());
        if (StringUtils.isEmpty(companyType)) {
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付 企业类型无效");
        }
        // List<MerchantCertInfoDO> merchantReportBenefitList =
        // merchantReportDto.getMerchantReportBenefitList();
        // List<MerchantCertInfoDO> merchantReportShareholderList =
        // merchantReportDto.getMerchantReportShareholderList();
        // if (CollectionUtils.isEmpty(merchantReportBenefitList)) {
        // return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付
        // 受益人至少一个");
        // }
        // if (CollectionUtils.isEmpty(merchantReportShareholderList)) {
        // return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付
        // 控股股东至少一个");
        // }
        // if (CollectionUtils.isEmpty(merchantReportBusiness.getSceneList())) {
        // return CommonResult.error(CommonResultCode.PARAMETER_MISSING.getCode(), "宝付
        // 必须存在网站信息");
        // }
        return CommonResult.success();
    }

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    public Map<String, Object> merchantReportParams(ChannelMerchantReportContext channelMerchantReportContext) {
        Map<String, Object> dataMap = new HashMap<>();
        MerchantReportDto merchantReportDto = channelMerchantReportContext.getMerchantReportDto();
        MerchantCardDO merchantReportCard = merchantReportDto.getMerchantReportCard();
        MerchantLicenseDO merchantReportLicense = merchantReportDto.getMerchantReportLicense();
        MerchantCertInfoDO merchantReportContact = merchantReportDto.getMerchantReportContact();
        MerchantCertInfoDO merchantReportLegal = merchantReportDto.getMerchantReportLegal();
        MerchantReportConfigDto merchantReportConfigDto = channelMerchantReportContext.getMerchantReportConfigDto();
        MerchantReportBusinessDO merchantReportBusiness = merchantReportDto.getMerchantReportBusiness();
        List<PayChannelDictDO> payChannelDictList = channelMerchantReportContext.getPayChannelDictList();
        dataMap.put("account_no", merchantReportCard.getCardNo());
        dataMap.put("settle_id", merchantReportCard.getBranchCode());
        dataMap.put("org_name", merchantReportLicense.getName());
        dataMap.put("email", merchantReportContact.getOtherValue());
        dataMap.put("legal_name", merchantReportLegal.getName());
        dataMap.put("legal_id_type", certType(merchantReportLegal.getCertType()));
        dataMap.put("legal_idcard", merchantReportLegal.getCertNo());
        dataMap.put("legal_idcard_start_expired", merchantReportLegal.getCertBeginDate());
        dataMap.put("legal_idcard_expired", merchantReportLegal.getCertEndDate());
        dataMap.put("legal_mobile", merchantReportLegal.getPhone());
        dataMap.put("business_name", merchantReportContact.getName());
        dataMap.put("business_id_type", certType(merchantReportLegal.getCertType()));
        dataMap.put("business_idcard", merchantReportContact.getCertNo());
        dataMap.put("business_idcard_start", merchantReportContact.getCertBeginDate());
        dataMap.put("business_idcard_expired", merchantReportContact.getCertEndDate());
        dataMap.put("business_mobile", merchantReportContact.getPhone());
        dataMap.put("business_license_no", merchantReportLicense.getLicenseCode());
        dataMap.put("business_license_start_expired", merchantReportLicense.getLicenseBeginDate());
        dataMap.put("business_license_expired", merchantReportLicense.getLicenseEndDate());
        dataMap.put("address", merchantReportLicense.getAddress());
        dataMap.put("registered_capital", merchantReportLicense.getRegisteredCapital());
        dataMap.put("business_scope", merchantReportLicense.getBusinessScope());
        Map<String, PayChannelDictDO> collect = payChannelDictList.stream().collect(Collectors.toMap(payChannelDictDO -> payChannelDictDO.getDictValue(), Function.identity()));
        PayChannelDictDO provinceDict = collect.get(merchantReportLicense.getProvinceCode());
        PayChannelDictDO cityDict = collect.get(merchantReportLicense.getCityCode());
        PayChannelDictDO areaDict = collect.get(merchantReportLicense.getAreaCode());
        if (provinceDict != null) {
            dataMap.put("province", provinceDict.getDictDesc());
        }
        if (cityDict != null) {
            dataMap.put("city", cityDict.getDictDesc());
        }
        if (areaDict != null) {
            dataMap.put("country", areaDict.getDictDesc());
        }

        dataMap.put("street", merchantReportLicense.getAddress());
        List<MerchantAccessScene> sceneList = merchantReportBusiness.getSceneList();
        if (CollectionUtils.isNotEmpty(sceneList)) {
            List<MerchantAccessScene> pcSceneList = sceneList.stream().filter(scene -> new Integer(1).equals(scene.getType())).collect(Collectors.toList());
            MerchantAccessScene pcScene = null;
            if (CollectionUtils.isEmpty(pcSceneList)) {
                pcScene = sceneList.get(0);
            }
            else {
                pcScene = pcSceneList.get(0);
            }
            dataMap.put("site_name", pcScene.getName());
            dataMap.put("web_site", pcScene.getWebUrl());
            dataMap.put("icp_code", pcScene.getIcp());
        }
        else {
            dataMap.put("site_name", "无网站");
            dataMap.put("web_site", "无");
            dataMap.put("icp_code", "无");
        }
        dataMap.put("open_type", "mobile");

        List<Map<String, Object>> beneficiaryList = new ArrayList();
        List<MerchantCertInfoDO> merchantReportBenefitList = merchantReportDto.getMerchantReportBenefitList();
        if (CollectionUtils.isEmpty(merchantReportBenefitList)) {
            merchantReportBenefitList = new ArrayList<>();
            merchantReportBenefitList.add(merchantReportLegal);
        }

        List<MerchantCertInfoDO> merchantReportShareholderList = merchantReportDto.getMerchantReportShareholderList();
        if (CollectionUtils.isEmpty(merchantReportShareholderList)) {
            merchantReportShareholderList = new ArrayList<>();
            merchantReportShareholderList.add(merchantReportLegal);
        }
        merchantReportBenefitList.stream().forEach(merchantCertInfoDO -> {
            // 受益人信息
            Map<String, Object> beneficiary = new HashMap<>();
            beneficiary.put("type", "02");
            beneficiary.put("beneficiary_name", merchantCertInfoDO.getName());
            beneficiary.put("beneficiary_id_type", certType(merchantCertInfoDO.getCertType()));
            beneficiary.put("beneficiary_id_no", merchantCertInfoDO.getCertNo());
            beneficiary.put("beneficiary_id_effDate", merchantCertInfoDO.getCertEndDate());
            beneficiary.put("beneficiary_id_offDate", merchantCertInfoDO.getCertBeginDate());
            beneficiary.put("beneficiary_phone", merchantCertInfoDO.getPhone());
            beneficiary.put("beneficiary_address", merchantCertInfoDO.getAddress());
            beneficiaryList.add(beneficiary);
        });

        merchantReportShareholderList.stream().forEach(merchantCertInfoDO -> {
            // 控股股东信息
            Map<String, Object> shareholder = new HashMap();
            shareholder.put("type", "01");
            shareholder.put("beneficiary_name", merchantCertInfoDO.getName());
            shareholder.put("beneficiary_id_type", certType(merchantCertInfoDO.getCertType()));
            shareholder.put("beneficiary_id_no", merchantCertInfoDO.getCertNo());
            shareholder.put("beneficiary_id_effDate", merchantCertInfoDO.getCertEndDate());
            shareholder.put("beneficiary_id_offDate", merchantCertInfoDO.getCertBeginDate());
            shareholder.put("beneficiary_phone", merchantCertInfoDO.getPhone());
            shareholder.put("beneficiary_address", merchantCertInfoDO.getAddress());
            beneficiaryList.add(shareholder);
        });
        // List beneficiaryListS = new ArrayList();
        // beneficiaryList.stream().forEach(beneficiary->{
        // beneficiaryListS.add(JsonUtils.toJsonString(beneficiary));
        // });
        dataMap.put("beneficiary_items", beneficiaryList);

        if (provinceDict != null) {
            dataMap.put("reg_province", provinceDict.getDictDesc());
        }
        if (cityDict != null) {
            dataMap.put("reg_city", cityDict.getDictDesc());
        }
        if (areaDict != null) {
            dataMap.put("reg_country", areaDict.getDictDesc());
        }
        dataMap.put("org_type", companyType(merchantReportLicense.getCompanyType()));
        dataMap.put("org_size", merchantReportBusiness.getCompanySizeType());
        dataMap.put("org_economy", merchantReportBusiness.getEconomyType());
        dataMap.put("org_industry", merchantReportBusiness.getMcc());
        dataMap.put("org_listing", merchantReportBusiness.getListingType());
        dataMap.put("account_type", "1");
        List<String> productIds = new ArrayList<>() {

            {
                add("104");
                add("210");
                add("211");
                add("212");
            }
        };
        MerchantReportConfigDto.FeeType inFeeType = merchantReportConfigDto.getInFeeType();
        MerchantReportConfigDto.FeeType outFeeType = merchantReportConfigDto.getOutFeeType();
        List<Map<String, Object>> productList = new ArrayList();
        productIds.stream().forEach(productId -> {
            Map<String, Object> prodList = new HashMap();
            prodList.put("product_id", productId);
            if ("104".equals(productId)) {
                prodList.put("charge_mode", "2");
                prodList.put("charge_value", inFeeType.getFee());
            }
            else {
                prodList.put("charge_value", outFeeType.getAmount());
                if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(outFeeType.getType())) {
                    prodList.put("charge_mode", "2");
                }
                else {
                    prodList.put("charge_mode", "1");
                }
            }
            productList.add(prodList);

        });
        // List product_list = new ArrayList();
        // productList.stream().forEach(product->{
        // product_list.add(JsonUtils.toJsonString(product));
        // });
        Map<String, Object> product_list = new HashMap<>();
        product_list.put("product_list", productList);
        dataMap.put("charge_info", product_list);
        Map<String, Object> bank_info = new HashMap();
        bank_info.put("bind_type", "0");
        dataMap.put("bank_info", bank_info);
        return dataMap;
    }

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    public CommonResult<File> zipFile(MerchantReportDto merchantReportDto) {
        String tempDir = uploadDirectory + File.separator + "baofu" + File.separator;
        MerchantReportInfoDO merchantAccessInfo = merchantReportDto.getMerchantReportInfo();
        // 商户全称，不能有特殊字符，仅可包含汉字、数字、字母 (需与营业执照一致，如遇提示重复，请在后面加数字1、2...，若为小微商户，请命名为 商户 xxx。)
        MerchantCertInfoDO merchantAccessLegal = merchantReportDto.getMerchantReportLegal();
        MerchantLicenseDO merchantAccessLicense = merchantReportDto.getMerchantReportLicense();
        MerchantCardDO merchantAccessCard = merchantReportDto.getMerchantReportCard();
        MerchantCertInfoDO merchantReportContact = merchantReportDto.getMerchantReportContact();
        MerchantReportBusinessDO merchantReportBusiness = merchantReportDto.getMerchantReportBusiness();
        File dir = new File(tempDir + merchantAccessInfo.getId());
        if (!dir.exists()) {
            Path parentDir = Paths.get(dir.getPath());
            try {
                Files.createDirectories(parentDir);
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        File dir_601 = new File(tempDir + merchantAccessInfo.getId() + File.separator + 601);
        if (!dir_601.exists()) {
            Path parentDir = Paths.get(dir_601.getPath());
            try {
                Files.createDirectories(parentDir);
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        File dir_other = new File(tempDir + merchantAccessInfo.getId() + File.separator + "other");
        if (!dir_other.exists()) {
            Path parentDir = Paths.get(dir_other.getPath());
            try {
                Files.createDirectories(parentDir);
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // 文件名 描述
        // 101 身份证正面，格式：jpg、png，小于5M
        // 102 身份证反面，格式：jpg、png，小于5M
        // 104 营业执照，格式：jpg、png，小于5M
        // 401 银行许可证（或开户凭证），格式：jpg、png，小于5M
        // 601 详见附件其他材料清单，打包成zip文件，
        // XW001 联系人证件正面，新网银行必传，格式：jpg、png
        // XW002 联系人证件反面，新网银行必传，格式：jpg、png
        // XW003 企业联系人授权书
        // XW004 企业法人授权书，非必填 ，格式：jpg、png
        // XW007 企业CA证书及电子签名授权书,新网银行必传，格式：jpg、png
        // 先处理601
        FileUtils.fileUpload(dir_601, merchantReportBusiness.getStoreHeaderUrl(), "601_1");
        FileUtils.fileUpload(dir_601, merchantReportBusiness.getStoreIndoorUrl(), "601_2");
        FileUtils.fileUpload(dir_601, merchantReportBusiness.getStoreCashierDeskUrl(), "601_3");
        // 要压缩的文件夹路径
        Path folderToZip = Paths.get(dir_601.getPath());
        // 输出的ZIP文件路径
        Path zipFilePath_601 = Paths.get(dir_other.getPath() + File.separator + "601.zip");
        try {
            // 调用方法压缩文件夹
            FileUtils.zipFolder(folderToZip, zipFilePath_601);
            log.info("Folder successfully zipped to:{} ", folderToZip);
        }
        catch (IOException e) {
            // System.err.println("Error zipping folder: " + e.getMessage());
            log.error("Folder successfully zipped to:{} ", e.getMessage(),e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR.getCode(), e.getMessage());
        }
        FileUtils.fileUpload(dir_other, merchantAccessLegal.getCertFrontUrl(), "101");
        FileUtils.fileUpload(dir_other, merchantAccessLegal.getCertBackUrl(), "102");
        FileUtils.fileUpload(dir_other, merchantAccessLicense.getLicenseUrl(), "104");
        FileUtils.fileUpload(dir_other, merchantAccessCard.getLicenseUrl(), "401");
        FileUtils.fileUpload(dir_other, merchantReportContact.getCertFrontUrl(), "XW001");
        FileUtils.fileUpload(dir_other, merchantReportContact.getCertBackUrl(), "XW002");
        FileUtils.fileUpload(dir_other, merchantAccessCard.getAuthUrl(), "XW004");
        // 输出的ZIP文件路径
        folderToZip = Paths.get(dir_other.getPath());
        Path zipFilePath = Paths.get(dir.getPath() + ".zip");
        try {
            // 调用方法压缩文件夹
            FileUtils.zipFolder(folderToZip, zipFilePath);
            log.info("Folder successfully zipped to:{} ", zipFilePath);
        }
        catch (IOException e) {
            // System.err.println("Error zipping folder: " + e.getMessage());
            log.error("Folder successfully zipped to:{} ", e.getMessage());
            return CommonResult.error(CommonResultCode.SERVICE_ERROR.getCode(), e.getMessage());
        }
        return CommonResult.success(zipFilePath.toFile());
    }

}
